home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 04 - 1988 / 04.04 Apr 88 / TearOffPalette Source / Palette.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-02-19  |  10.9 KB  |  416 lines  |  [TEXT/KAHL]

  1. /*
  2. ----------------------------------------------------------------------------------------------------
  3. T E A R O F F   P A L E T T E
  4.  
  5.     version 1.0
  6.     by Don Melton and Mike Ritter
  7.     
  8.     Copyright (C)1987, 1988 by Impulse Technologies, Inc., all rights reserved. 
  9.     
  10.     Filename:            Palette.c
  11.     Font:                    Monaco, 9 point
  12.     Tab setting:    2
  13.     Compiler:            LightspeedC 2.15, Project type: APPL, Creator: TOPD
  14.     Segment:            Main */
  15.  
  16.  
  17.  
  18. /*
  19. ----------------------------------------------------------------------------------------------------
  20. GLOBAL CONSTANT DEFINITIONS AND VARIABLE DECLARATIONS */
  21.  
  22. #include "Constants.h"
  23. #include "Variables.h"
  24.  
  25. /*
  26. ----------------------------------------------------------------------------------------------------
  27. EXTERNAL FUNCTION DECLARATIONS */
  28.  
  29. extern void ActivateDocument();                            /* Window.c */
  30. extern short GetMenuBarHeight();                        /* Interface.c */
  31.  
  32. /*
  33. ----------------------------------------------------------------------------------------------------
  34. FORWARD FUNCTION DECLARATIONS */
  35.  
  36. void LocateWindows();
  37. void HiliteUserWindows();
  38. short ActiveWindow();
  39. void DoDragWindow();
  40. void DoSelectWindow();
  41. void SendToBack();
  42. void Drag();
  43.  
  44.  
  45.  
  46. /*
  47. ----------------------------------------------------------------------------------------------------
  48. LOCATE WINDOWS
  49.  
  50.     Find the TopWindow whether it belongs to the application or not. Also find the TopPalette, the
  51.     BottomPalette, and the TopDocument. These globals will all point to visible windows or nil. If
  52.     the TopDocument is above any visible palette, adjust the order of the windows. If a visible
  53.     non-application window is between any palettes and the TopDocument, adjust the order of the
  54.     windows. This function replaces most uses of FrontWindow() in the application. */
  55.  
  56. void LocateWindows()
  57. {
  58.     short palettesFound;
  59.     Boolean inOrder;
  60.     WindowPeek next;
  61.     WindowPeek bottom;
  62.     
  63.     /* Initialize the globals before the search is begun. */
  64.     TopWindow = TopPalette = TopDocument = nil;
  65.     /* Make sure all SendBehind() and NewWindow() calls bring a window to the front if there are no
  66.     visible palettes. */
  67.     BottomPalette = BRING_TO_FRONT;
  68.     
  69.     palettesFound = 0;
  70.     inOrder = true;
  71.     
  72.     for(next = WindowList; next != nil; next = next->nextWindow) {
  73.     
  74.         if(next->visible) {
  75.         
  76.             if(TopWindow == nil) {
  77.                 /* First visible window. */
  78.                 TopWindow = (WindowPtr) next;
  79.             }
  80.             if(next->windowKind == userKind) {
  81.             
  82.                 if(next->refCon == DOCUMENT_WINDOW) {
  83.                 
  84.                     if(TopDocument == nil) {
  85.                         /* First visible Document. */
  86.                         TopDocument = (WindowPtr) next;
  87.                         
  88.                         if(palettesFound == PALETTE_COUNT) {
  89.                             /* If all the palettes are found exit the search loop. */
  90.                             break;
  91.                         }
  92.                     }
  93.                 }
  94.                 else {
  95.                 
  96.                     if(TopPalette == nil) {
  97.                         /* First visible palette. */
  98.                         TopPalette = (WindowPtr) next;
  99.                     }
  100.                     /* BottomPalette always points to the last visible palette found. */
  101.                     BottomPalette = (WindowPtr) next;
  102.                 }
  103.             }
  104.             else {
  105.             
  106.                 if((TopPalette != nil) || (TopDocument != nil)) {
  107.                     /* Shucks, a non-application window is visible between the palettes and TopDocument. */
  108.                     inOrder = false;
  109.                 }
  110.             }
  111.         }
  112.         /* All windows before the last palette get to this point. */
  113.         if((next->windowKind == userKind) && (next->refCon != DOCUMENT_WINDOW)) {
  114.             palettesFound++;
  115.             
  116.             if((TopDocument != nil) && (next->visible)) {
  117.                 /* A visible palette is beneath the TopDocument. */
  118.                 
  119.                 if(TopDocument == TopWindow) {
  120.                     /* Bring the TopPalette to the front. */
  121.                     SelectWindow(next);
  122.                     TopWindow = (WindowPtr) next;
  123.                 }
  124.                 else {
  125.                     /* Send TopDocument behind BottomPalette. */
  126.                     SendBehind(TopDocument, next);
  127.                 }
  128.                 next = (WindowPeek) TopDocument;
  129.                 
  130.                 if(palettesFound == PALETTE_COUNT) {
  131.                     /* If all the palettes are found exit the search loop. */
  132.                     break;
  133.                 }
  134.             }
  135.         }
  136.     }
  137.     if((!inOrder) && (TopPalette != nil)) {
  138.     
  139.         if(TopDocument != nil) {
  140.             bottom = (WindowPeek) TopDocument;
  141.         }
  142.         else {
  143.             bottom = (WindowPeek) BottomPalette;
  144.         }
  145.         for(next = (WindowPeek) TopPalette; next != nil; next = next->nextWindow) {
  146.         
  147.             if(next != bottom) {
  148.             
  149.                 if(next->windowKind != userKind) {
  150.                     /* Remove the non-application window. */
  151.                     SendBehind(next, bottom);
  152.                     /* Start over. */
  153.                     next = (WindowPeek) TopPalette;
  154.                 }
  155.             }
  156.             else {
  157.                 break;
  158.             }
  159.         }
  160.     }
  161. }
  162.  
  163. /*
  164. ----------------------------------------------------------------------------------------------------
  165. HILITE USER WINDOWS */
  166.  
  167. void HiliteUserWindows() 
  168. {
  169.     WindowPeek bottom;
  170.     WindowPeek next;
  171.     Boolean hilite;
  172.     short index;
  173.     
  174.     if(TopPalette != nil) {
  175.     
  176.         if(TopWindow == TopPalette) {
  177.             hilite = true;
  178.         }
  179.         else {
  180.             hilite = false;
  181.         }
  182.         for(index = 0; index < PALETTE_COUNT; index++) {
  183.             HiliteWindow(Palettes[index], hilite);
  184.         }
  185.         if(TopDocument != nil) {
  186.         
  187.             HiliteWindow(TopDocument, hilite);
  188.             /* Unhilite the remaining document windows. */
  189.             for(next = ((WindowPeek) TopDocument)->nextWindow; next != nil; next = next->nextWindow) {
  190.             
  191.                 if((next->windowKind == userKind) && (next->refCon == DOCUMENT_WINDOW)) {
  192.                     ActivateDocument(next, false);
  193.                 }
  194.             }
  195.         }
  196.     }
  197. }
  198.  
  199. /*
  200. ----------------------------------------------------------------------------------------------------
  201. ACTIVE WINDOW
  202.  
  203.     Return true if whichWindow is a palette or the TopDocument and the application is active. */
  204.  
  205. short ActiveWindow(whichWindow)
  206. WindowPtr whichWindow;
  207. {
  208.     if(whichWindow != nil) {
  209.     
  210.         if((((WindowPeek) TopWindow)->windowKind == userKind)
  211.                 && ((whichWindow == TopDocument)
  212.                 || (((WindowPeek) whichWindow)->refCon != DOCUMENT_WINDOW))) {
  213.             return(true);
  214.         }
  215.     }
  216.     return(false);
  217. }
  218.  
  219. /*
  220. ----------------------------------------------------------------------------------------------------
  221. DO DRAG WINDOW
  222.  
  223.     Since DragWindow() automatically brings a window to the front if it's not already the front
  224.     window, it must be replaced by the application to keep palettes floating above documents. */
  225.  
  226. void DoDragWindow(whichWindow)
  227. WindowPtr whichWindow;
  228. {
  229.     if(Event.modifiers & optionKey) {
  230.         /* This is an optional extension of the Macintosh interface. */
  231.         SendToBack(whichWindow);
  232.     }
  233.     else {
  234.     
  235.         if(Event.modifiers & cmdKey) {
  236.             Drag(whichWindow);
  237.         }
  238.         else {
  239.         
  240.             if(!ActiveWindow(whichWindow)) {
  241.                 DoSelectWindow(whichWindow);
  242.             }
  243.             else {
  244.             
  245.                 if((((WindowPeek) whichWindow)->refCon != DOCUMENT_WINDOW)
  246.                         && (whichWindow != TopPalette)) {
  247.                     BringToFront(whichWindow);
  248.                     /* Force the palette to be updated before it is dragged. */
  249.                     SetPort(whichWindow);
  250.                     UpdatePalette(whichWindow);
  251.                 }
  252.                 Drag(whichWindow);
  253.             }
  254.         }
  255.     }
  256. }
  257.  
  258. /*
  259. ----------------------------------------------------------------------------------------------------
  260. DO SELECT WINDOW
  261.  
  262.     Since SelectWindow() brings any window to the front, it must be replaced by the application to
  263.     keep palettes floating above documents. */
  264.  
  265. void DoSelectWindow(whichWindow)
  266. WindowPtr whichWindow;
  267. {
  268.     RgnHandle updateRgn;
  269.     
  270.     if(((WindowPeek) whichWindow)->refCon == DOCUMENT_WINDOW) {
  271.     
  272.         if(TopPalette != nil) {
  273.             /* Calculate window area not visible that will need to be updated. */
  274.             CopyRgn(whichWindow->visRgn, updateRgn = NewRgn());
  275.             OffsetRgn(updateRgn,
  276.                     (*((WindowPeek) whichWindow)->contRgn)->rgnBBox.left,
  277.                     (*((WindowPeek) whichWindow)->contRgn)->rgnBBox.top);
  278.             DiffRgn(((WindowPeek) whichWindow)->strucRgn, updateRgn, updateRgn);
  279.             
  280.             /* Move the document below the BottomPalette. */
  281.             SendBehind(whichWindow, BottomPalette);
  282.             CalcVisBehind(whichWindow, updateRgn);
  283.             PaintOne(whichWindow, updateRgn);
  284.             
  285.             DisposeRgn(updateRgn);
  286.             
  287.             if(TopPalette != TopWindow) {
  288.                 /* Bring all active application windows forward by generating an activate event. */
  289.                 SelectWindow(TopPalette);
  290.             }
  291.             else {
  292.                 /* Ensure whichWindow and its controls are hilited properly. */
  293.                 ActivateDocument(whichWindow, true);
  294.             } 
  295.             /* Ensure whichWindow and its controls are unhilited properly. */
  296.             ActivateDocument(TopDocument, false);
  297.         }
  298.         else {
  299.             /* No Palettes, bring the document to the front and generate an activate event. */
  300.             SelectWindow(whichWindow);
  301.         }
  302.     }
  303.     else {
  304.         if(((WindowPeek) TopWindow)->windowKind == userKind) {
  305.             /* Bring the palette to the front but don't generate an activate event. */
  306.             BringToFront(whichWindow);
  307.         }
  308.         else {
  309.             /* Bring the palette to the front and generate an activate event. */
  310.             SelectWindow(whichWindow);
  311.         }
  312.     }
  313. }
  314.  
  315. /*
  316. ----------------------------------------------------------------------------------------------------
  317. SEND TO BACK */
  318.  
  319. void SendToBack(whichWindow)
  320. WindowPtr whichWindow;
  321. {
  322.     WindowPeek next;
  323.     WindowPtr below;
  324.     
  325.     if(((WindowPeek) whichWindow)->refCon == DOCUMENT_WINDOW) {
  326.     
  327.         below = whichWindow;
  328.         
  329.         /* Find the document below TopDocument. Documents are always visible. */
  330.         for(next = ((WindowPeek) whichWindow)->nextWindow; next != nil; next = next->nextWindow) {
  331.         
  332.             if((next->windowKind == userKind) && (next->refCon == DOCUMENT_WINDOW)) {
  333.                 below = (WindowPtr) next;
  334.                 break;
  335.             }
  336.         }
  337.         if(whichWindow != below) {
  338.             /* Send the document all the way to the back. */
  339.             SendBehind(whichWindow, nil);
  340.             
  341.             if(TopPalette == TopWindow) {
  342.                 /* Ensure whichWindow and its controls are unhilited properly. */
  343.                 ActivateDocument(whichWindow, false);
  344.                 
  345.                 /* Find the new TopDocument. */
  346.                 LocateWindows();
  347.                 /* Ensure the TopDocument and its controls are hilited properly. */
  348.                 ActivateDocument(TopDocument, true);
  349.             }
  350.         }
  351.     } 
  352.     else {
  353.     
  354.         if((whichWindow != BottomPalette) && (TopPalette != BottomPalette)) {
  355.             /* Move the palette behind the BottomPalette. */
  356.             SendBehind(whichWindow, BottomPalette);
  357.         }
  358.     }
  359. }
  360.  
  361. /*
  362. ----------------------------------------------------------------------------------------------------
  363. DRAG */
  364.  
  365. void Drag(whichWindow)
  366. WindowPtr whichWindow;
  367. {
  368.     GrafPtr savePort;
  369.     Rect dragLimit;
  370.     RgnHandle dragRgn;
  371.     long result;
  372.     Point move;
  373.     Rect *portBounds;
  374.     
  375.     if(WaitMouseUp()) {
  376.         GetPort(&savePort);
  377.         SetPort(WMgrPort);
  378.         
  379.         SetClip(GrayRgn);
  380.         
  381.         /* Ensure the drag outline does not get drawn through the windows above whichWindow. */
  382.         ClipAbove(whichWindow);
  383.         
  384.         dragLimit = screenBits.bounds;
  385.         dragLimit.top = GetMenuBarHeight();
  386.         
  387.         CopyRgn(((WindowPeek) whichWindow)->strucRgn, dragRgn = NewRgn());
  388.         
  389.         /* Drag the outline of the window around the screen. */
  390.         result = DragGrayRgn(dragRgn, Event.where, &dragLimit, &dragLimit, noConstraint, nil);
  391.         
  392.         move.v = result >> 16; /* HiWord(result). */
  393.         move.h = result & 0xFFFF; /* LoWord(result). */
  394.         
  395.         if(move.v != 0x8000) {
  396.         
  397.             /* The mouse button has been released inside dragLimit. */
  398.             /* See 'Inside Macintosh Volume I,' pages 294-295, for expalnation of 0x8000. */
  399.             if(((CGrafPtr) whichWindow)->portVersion & 0xc000) {
  400.                 /* The window is a color port. */
  401.                 portBounds = &(*((CGrafPtr) whichWindow)->portPixMap)->bounds;
  402.             }
  403.             else {
  404.                 /* The window is an old-style port. */
  405.                 portBounds = &whichWindow->portBits.bounds;
  406.             }
  407.             move.v += whichWindow->portRect.top - portBounds->top;
  408.             move.h += whichWindow->portRect.left - portBounds->left;
  409.             
  410.             MoveWindow(whichWindow, move.h, move.v, false);
  411.         }
  412.         DisposeRgn(dragRgn);
  413.         SetPort(savePort);
  414.     }
  415. }
  416.